#include "Subsystems/BlockBehaviors/SubsystemMagmaBlockBehavior.h"
#include "Subsystems/BlockBehaviors/SubsystemFireBlockBehavior.h"

#include "Subsystems/SubsystemTerrain.h"
#include "Subsystems/SubsystemWeather.h"
#include "Subsystems/SubsystemTimeOfDay.h"

#include "Managers/BlocksManager.h"

#include "Blocks/FluidBlock.h"
#include "Blocks/MagmaBlock.h"
#include "Blocks/BasaltBlock.h"
#include "Blocks/WaterBlock.h"
#include "Blocks/GrassBlock.h"
#include "Blocks/DirtBlock.h"
#include "Blocks/SnowBlock.h"
#include "Blocks/IceBlock.h"

#include "GameSingleton.h"

namespace PocketSurvival
{
    SubsystemMagmaBlockBehavior::SubsystemMagmaBlockBehavior() : SubsystemFluidBlockBehavior(true)  
    {
        m_handleBlocks.push_back(MagmaBlock::Index());
    }

    void SubsystemMagmaBlockBehavior::onBlockAdded(int32_t value, int32_t oldValue, int32_t x, int32_t y, int32_t z)
    {
		SubsystemFluidBlockBehavior::onBlockAdded(value, oldValue, x, y, z);
		for (int32_t i = -1; i <= 1; i++)
		{
			for (int32_t j = -1; j <= 1; j++)
			{
				for (int32_t k = -1; k <= 1; k++)
				{
					applyMagmaNeighborhoodEffect(x + i, y + j, z + k);
				}
			}
		}
    }

    bool SubsystemMagmaBlockBehavior::onFluidInteract(int32_t interactValue, int32_t x, int32_t y, int32_t z, int32_t fluidValue)
    {
		if (GameSingleton::blocksManager->blocks[Terrain::ExtractContents(interactValue)]->isBlock<WaterBlock*>() == true)
		{
            subsystemTerrain->destroyCell(0, x, y, z, 0, false);
			set(x, y, z, BasaltBlock::Index());
			return true;
		}
		return SubsystemFluidBlockBehavior::onFluidInteract(interactValue, x, y, z, fluidValue);
    }

    void SubsystemMagmaBlockBehavior::onNeighborBlockChanged(int32_t x, int32_t y, int32_t z, int32_t neighborX, int32_t neighborY, int32_t neighborZ)
    {
        SubsystemFluidBlockBehavior::onNeighborBlockChanged(x, y, z, neighborX, neighborY, neighborZ);
        applyMagmaNeighborhoodEffect(neighborX, neighborY, neighborZ);
    }

    void SubsystemMagmaBlockBehavior::applyMagmaNeighborhoodEffect(int32_t x, int32_t y, int32_t z)
    {
        m_fireBlockBehavior->setCellOnFire(Point3(x, y, z), 1.0f);
        switch (m_terrain->getCellContents(x, y, z))
        {
        case SnowBlock::Index():
        case IceBlock::Index():
            m_terrain->destroyCell(0, x, y, z, 0, false);
        	break;
        case GrassBlock::Index():
            m_terrain->changeCell(x, y, z, DirtBlock::Index());
        	break;
        }
    }


    void SubsystemMagmaBlockBehavior::update(float dt)
    {
        if(m_timeOfDay->periodicGameTimeEvent(2.0, 0.0))
        {
            spreadFluid();
        }
    }

    void SubsystemMagmaBlockBehavior::load(const nlohmann::json& json)
    {
        SubsystemFluidBlockBehavior::load(json);
        m_timeOfDay = GameSingleton::singletonPtr->getSingleton<SubsystemTimeOfDay>();
        m_fireBlockBehavior = GameSingleton::singletonPtr->getSingleton<SubsystemFireBlockBehavior>();
        m_terrain = GameSingleton::singletonPtr->getSingleton<SubsystemTerrain>();

        m_fluidBlock = GameSingleton::blocksManager->blocks[MagmaBlock::Index()]->asBlock<FluidBlock*>();
        m_fluidType = FluidType::Magma;
    }

    void SubsystemMagmaBlockBehavior::saveToMsgJson(nlohmann::json &jsonData) {}
    
    static const std::string subsystemName = "MagmaBlockBehavior";
    const std::string& SubsystemMagmaBlockBehavior::getName() const
    {
        return subsystemName;
    }
    SubUpdateType SubsystemMagmaBlockBehavior::getUpdateType()
    {
        return SubUpdateType::MultiThreadUpdate;
    }


} // namespace PocketSurvival
